﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Novice.Units.Tree
{
    public class TreeUnitsAlgebra: IUnitAlgebra
    {
        public bool CanWorkWith(IUnit unit)
        {
            return unit is Unit;
        }

        public bool Convert(double valueFrom, IUnit from, IUnit to, out double valueTo)
        {
            if (from == null) throw new ArgumentNullException("from");
            if (to == null) throw new ArgumentNullException("to");
            var fromUnit = from as Unit;
            var toUnit = to as Unit;
            if (fromUnit == null || toUnit == null) throw new UnsupportedUnitException();

            double c1, c2;
            if (fromUnit.GetBaseUnit(out c1) != toUnit.GetBaseUnit(out c2))
            {
                valueTo = valueFrom;
                return false;
            }

            valueTo = valueFrom*c1/c2;
            return true;
        }

        public bool CheckEquivalence(IUnit left, IUnit right)
        {
            if (left == null) throw new ArgumentNullException("left");
            if (right == null) throw new ArgumentNullException("right");
            var leftUnit = left as Unit;
            var rightUnit = right as Unit;
            if(leftUnit == null || rightUnit == null) throw new UnsupportedUnitException();

            return leftUnit.GetBaseUnit() == rightUnit.GetBaseUnit();
        }
    }

    public static class UnitExtensions
    {
        static public Unit GetBaseUnit(this Unit unit, out double coefficient)
        {
            coefficient = 1.0;
            while (unit.BaseUnit != null)
            {
                coefficient *= unit.Coefficient;
                unit = unit.BaseUnit;
            }
            return unit;
        }

        static public Unit GetBaseUnit(this Unit unit)
        {
            while (unit.BaseUnit != null)
            {
                unit = unit.BaseUnit;
            }
            return unit;
        }
    }
}
